/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * htap_delta_table.h
 *
 *
 * IDENTIFICATION
 * src/include/storage/htap/htap_delta_table.h
 *
 * -------------------------------------------------------------------------
 */

#ifndef HTAP_DELTA_TABLE_H
#define HTAP_DELTA_TABLE_H

#include <stdint.h>
#include "utils/palloc.h"
#include "postgres_ext.h"
#include "c.h"
#include "vecexecutor/vectorbatch.h"
#include "access/imcs/imcu.h"
#include "access/htup.h"
#include "access/imcs/imcs_vector.h"

class ScalarVector;
class IMCSDesc;

namespace MOT {
class Table;
class Column;
class Row;
class TxnManager;
class Index;
class Sentinel;
class IndexIterator;
class MaxKey;
}

namespace htap {
class HTAPDeleteMap;

class HTAPDelta : public BaseObject {
public:
    class ScanContext : public BaseObject {
    public:
        ScanContext(uint64_t startKey = 0);
        virtual ~ScanContext();
        void Destroy() {}

        void reset();
        uint32_t getStartIndex()
        {
            return m_startKey;
        }

    private:
        void setFinished();

        MOT::IndexIterator *m_cursor;
        bool m_isFinished;
        uint64_t m_startKey;

        friend HTAPDelta;
    };

    class StatsScanContext : public ScanContext {
    public:
        StatsScanContext();
        ~StatsScanContext();

    private:
        MOT::Row *m_row;

        friend HTAPDelta;
    };

    class LookupContext {
    public:
        LookupContext() {}
        ~LookupContext() {}

    private:
        char _buf[1024];
        MOT::MaxKey *m_key;
        MOT::Index *m_index;
        friend HTAPDelta;
    };

public:
    HTAPDelta(bool isFlush = false, bool useTxn = true);
    virtual ~HTAPDelta();
    virtual void Destroy();

    /* *
     * @brief Build the extractor object for input table ID and CSN
     * @param tableID current table ID
     * @param csn current CSN
     */
    bool BuildIndexOnDeltaTable(Oid tableID, CommitSeqNo csn);

    bool buildWithAllCSNVersion(Oid tableID, CommitSeqNo csn);

    /* *
     * @brief ReBuild the extractor object using existing CSN and new table ID
     * @param tableID current table ID
     */
    bool BuildIndexOnNewDeltaTable(Oid tableID);

    inline Oid GetTableId() const
    {
        return m_tableID;
    }
    inline MOT::Table *GetTable() const
    {
        return m_currTable;
    }
    inline CommitSeqNo GetCsn() const
    {
        return m_csn;
    }

    bool BuildBatchDelMask(HTAPDeleteMap *batch_del_mask_result, IMCU *ctid_imcu, IMCUDesc *ctid_cu_desc, int ctid_imcu_rows,
        HTAPDeleteMap *imcs_del_mask_HTAPDeleteMap) const;
    void scan(VectorBatch *vec_batch_out, const TupleDesc &rd_att, ScanContext &ctx, uint32_t maxOutSize,
        int32_t numberOfColumns, int32_t *colIDArray) const;
    void scanForFlush(IMCSBulkloadRows *batch_rows_ptr, Datum *values, bool *nulls, size_t *lengths,
        int2 *imcs_to_values, const TupleDesc &imcs_rd_att, ScanContext &ctx, uint32_t maxOutSize) const;
    bool checkRowgroup(LookupContext &ctx, IMCUDesc *ctid_cu_desc) const;
    bool checkIMCU(IMCUDesc *ctid_cu_desc) const;
    uint64_t getNextCtid(ScanContext &ctx, uint32_t num_rows_to_advance) const;

    uint64_t minCtid() const
    {
        return m_minCtid;
    }
    uint64_t maxCtid() const
    {
        return m_maxCtid;
    }

    HeapTuple delta_scan_getnexttuple(StatsScanContext &ctx);
    bool checkDeltaStatus();
    bool lookUp(char &foundRecordType, LookupContext &ctx, const ItemPointerData &data) const;
    void initLookupCtx(LookupContext &ctx) const;
    bool hasData() const
    {
        return m_hasData;
    }
    uint32_t newRecords() const
    {
        return m_newRecords;
    }
    uint32_t addRecords();

private:
    void reset();
    bool FillBatch(VectorBatch *vec_batch_out, const TupleDesc &rd_att, uint32_t &recordIdx, void *record,
        int32_t numberOfColumns, int32_t *colIDArray) const;
    bool FillRow(Datum *values, bool *nulls, size_t *lengths, const TupleDesc &imcs_rd_att,
        void *record) const;
    bool FillColumn(ScalarVector *colVec, int2 attlen, MOT::Column *col, Oid type, int nullColIdx,
        uint32_t recordIdx, void *record) const;
    bool BuildIndex();
    MOT::Row *getFirstRelevantRow(MOT::IndexIterator *cursor) const;
    bool initScanContext(ScanContext &ctx) const;

    inline bool isCTIDInRange(uint64_t ctid) const
    {
        return (ctid >= m_minCtid && ctid <= m_maxCtid);
    }

    bool setMin(MOT::Index *ix);
    bool setMax(MOT::Index *ix);
    inline MOT::Row *getRow(MOT::Sentinel *sentinel) const;

private:
    uint64_t m_minCtid;
    uint64_t m_maxCtid;
    Oid m_tableID;
    CommitSeqNo m_csn;
    CommitSeqNo m_lastFlushedCsn;
    MOT::Table *m_currTable;
    bool m_hasData;
    bool m_isFlush;
    bool m_useTxn;
    uint32_t m_newRecords;
    MOT::TxnManager *m_txn;

    mutable uint32_t m_delIterIdx; /* need it just for debug reason */
    mutable uint32_t m_scanIterIdx; /* need it just for debug reason */
};
}

#endif // HTAP_DELTA_TABLE_H
